//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <asm.h>

//    AREA |.text|,ALIGN=2,CODE,READONLY
    .text

#define DEBUGINTERLOCK  0

#define INVALIDREF  0xBADBADBA

//==========================================================================
//Int32 InterlockedIncrement(PInt32 pAddend)

    .global C_SYMBOL(InterlockedIncrement)
C_SYMBOL(InterlockedIncrement):
    ldr r2, =INVALIDREF
    swp r1, r2, [r0]   //(r0)-->r1, r2->(r0)
    cmp r1, r2

#if DEBUGINTERLOCK
    beq PUTCHAR1
#else
    beq _InterlockedIncrement
#endif

    add r1, r1, #1
    str r1, [r0]
    mov r0, r1
    mov pc, lr

#if DEBUGINTERLOCK
PUTCHAR1
    IMPORT DBG_SendChar
    stmdb sp!, {r0,lr}
    mov r0, #0x41
    bl DBG_SendChar
    ldmia sp!, {r0,lr}
    b _InterlockedIncrement
#endif

//==========================================================================
//Int32 InterlockedDecrement(PInt32 pAddend)

    .global C_SYMBOL(InterlockedDecrement)
C_SYMBOL(InterlockedDecrement):
    ldr r2, =INVALIDREF
    swp r1, r2, [r0]    //(r0)-->r1, r2->(r0)
    cmp r1, r2

#if DEBUGINTERLOCK
    beq PUTCHAR2
#else
    beq _InterlockedDecrement
#endif

    add r1, r1, #-1
    str r1, [r0]
    mov r0, r1
    mov pc, lr

#if DEBUGINTERLOCK
PUTCHAR2
    stmdb sp!, {r0,lr}
    mov r0, #0x42
    bl DBG_SendChar
    ldmia sp!, {r0,lr}
    b _InterlockedDecrement
#endif

//==========================================================================
//Int32 InterlockedExchangeAdd(PInt32 pAddend, Int32 Increment)

    .global C_SYMBOL(InterlockedExchangeAdd)
C_SYMBOL(InterlockedExchangeAdd):
    ldr r2, =INVALIDREF
    swp r3, r2, [r0]  //(r0)-->r3 , r2-->(r0)
    cmp r3, r2

#if DEBUGINTERLOCK
    beq PUTCHAR3
#else
    beq _InterlockedExchangeAdd
#endif

    add r3, r3, r1
    str r3, [r0]
    mov r0, r3
    mov pc, lr

#if DEBUGINTERLOCK
PUTCHAR3
    stmdb sp!, {r0,r1,lr}
    mov r0, #0x43
    bl DBG_SendChar
    ldmia sp!, {r0,r1,lr}
    b _InterlockedExchangeAdd
#endif
//==========================================================================
//Int32 InterlockedExchange(PInt32 Target, Int32 Value)

    .global C_SYMBOL(InterlockedExchange)
C_SYMBOL(InterlockedExchange):
    swp r1, r1, [r0]
    mov r0, r1
    mov pc, lr

//==========================================================================
//EXTERN_C Int32 InterlockedCompareExchange(
//              PInt32 destination, Int32 exchange, Int32 comperand)
    .global C_SYMBOL(InterlockedCompareExchange)
C_SYMBOL(InterlockedCompareExchange):
    mov r3, r0            // 1st addr to r3
    ldr r12, =INVALIDREF
CompareExchangeLoop:
    swp r0, r12, [r3]      // swp old value to r0
    cmp r12, r0

#if DEBUGINTERLOCK
    beq PUTCHAR4
#else
    beq CompareExchangeLoop
#endif

    cmp r2, r0            //compare old value and comperand
    streq r1, [r3]          // exchange---> destination
    strne r0, [r3]          // restore the frist arg

    mov pc, lr

#if DEBUGINTERLOCK
PUTCHAR4
    stmdb sp!, {r0,r1,lr}
    mov r0, #0x44
    bl DBG_SendChar
    ldmia sp!, {r0,r1,lr}
    b CompareExchangeLoop
#endif

//==========================================================================
// disable fiq and irq, return r0 include the cpsr content

    .global C_SYMBOL(save_flags_cli)
C_SYMBOL(save_flags_cli):
    mrs     r0, cpsr    // return current flags for restore later
    orr     r12, r0, #0xC0  //cli
    msr     cpsr_cf, r12

    mov     pc, lr

//==========================================================================
// r0 include the cpsr content

    .global C_SYMBOL(restore_flags)
C_SYMBOL(restore_flags):
    msr     cpsr_cf, r0
    mov     pc, lr

//==========================================================================
//
// Cli()
// Disable the maskable processor interrupts.
// Disable irq and fiq interrupts.
// zero---enable, one---disable.
    .global C_SYMBOL(Cli)
C_SYMBOL(Cli):
    mrs     r0, cpsr
    orr     r0, r0, #0xC0
    msr     cpsr_cf, r0
    mov     pc, lr

//==========================================================================
// Sti()
// Enable maskable interrupts
// Enable irq and fiq interrupts.
// if should we enable or disable irq and fiq respectively
    .global C_SYMBOL(Sti)
C_SYMBOL(Sti):
    mrs     r0, cpsr
    bic     r0, r0, #0xC0
    msr     cpsr_cf, r0
    mov     pc, lr

//==========================================================================
//BOOL InterruptsDisabled(void)
//check if interrupts disabled ?
    .global C_SYMBOL(InterruptsDisabled)
C_SYMBOL(InterruptsDisabled):
    mrs     r0, cpsr
    and     r0, r0, #0x80
    mov     pc, lr

//==========================================================================
    .global C_SYMBOL(GetCpsr)
C_SYMBOL(GetCpsr):
    mrs     r0, cpsr
    mov     pc, lr

//==========================================================================
//Address GetSP(void)
//get current stack pointer
    .global C_SYMBOL(GetSP)
C_SYMBOL(GetSP):
    mov     r0, sp
    mov     pc, lr
//end of GetSP
//==========================================================================
//

//---------------------------------------------------
//EXTERN_C void sys_cmpxchg(PInt32, Int32, Int32)
    .global C_SYMBOL(sys_cmpxchg)
C_SYMBOL(sys_cmpxchg):
    mrs		r3,cpsr
	tst	    r3,#0x0f
	bne     knl_codex

    swi 21  //syscall_comxchg
    mov pc, lr   //return
knl_codex:

    MRS     r3, cpsr    //save cpsr in r3
    orr     r12, r3, #0xc0
    MSR     cpsr_cf, r12
  	ldr     r12, [r0]
  	cmp     r12, r2
    swpeq   r1, r1, [r0]
    moveq   r0, r1      //if swap, return old value
    movne   r0, r12     //if not swap, return old value too
    MSR     cpsr_cf, r3 //restor cpsr
	mov     pc, lr
//---------------------------------------------------

